#include "msg_pack.h"
#include "myds.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>

msg_pack_t *pack_create(PACK_TYPE type)
{
    msg_pack_t *p = (msg_pack_t *)malloc(sizeof(msg_pack_t));
    p->totalLen = 4 + 4 + 4;
    p->type = type;
    p->fieldNum = 0;
    p->startField = NULL;
    p->endField = NULL;
    return p;
}

void pack_destroy(msg_pack_t *pack)
{
    // 销毁字段
    field_t *p = pack->startField;
    for (int i = 0; i < pack->fieldNum; i++)
    {
        field_t *temp = p;
        p = p->next;
        //
        free(temp->content);
        free(temp);
    }
    // 销毁自己
    free(pack);
}

void pack_add_field(msg_pack_t *pack, int filedLen, char *content)
{
    field_t *field = (field_t *)malloc(sizeof(field_t));
    field->filedLen = filedLen;
    field->content = (char *)malloc(sizeof(char) * filedLen);
    field->next = NULL;
    memcpy(field->content, content, filedLen);
    if (pack->fieldNum == 0)
    {
        pack->endField = field;
        pack->startField = field;
        pack->fieldNum += 1;
        pack->totalLen += 4 + filedLen;
        return;
    }
    // printf("11111: fieldLen=[%d],content=[%s]\n",filedLen, content);
    pack->endField->next = field; // 尾插
    pack->endField = field;
    pack->fieldNum += 1;
    pack->totalLen += 4 + filedLen;
    // printf("11111: pack->fieldNum=[%d],pack->totalLen=[%d]\n", pack->fieldNum,pack->totalLen);
}

void pack_2_buf(msg_pack_t *pack, char *buf)
{
    memcpy(buf, &(pack->totalLen), 4);
    buf += 4;
    memcpy(buf, &(pack->type), 4);
    buf += 4;
    memcpy(buf, &(pack->fieldNum), 4);
    buf += 4;
    //
    field_t *p = pack->startField;
    for (int i = 0; i < pack->fieldNum; i++)
    {
        memcpy(buf, &(p->filedLen), 4);
        buf += 4;
        memcpy(buf, p->content, p->filedLen);
        buf += p->filedLen;
        p = p->next;
    }
}

msg_pack_t *pack_from_socket(int fd)
{
    unsigned int totalLen;
    int ret = recv(fd, &totalLen, 4, 0);
    // printf("totalLen=[%d], ret=[%d]\n", totalLen, ret);
    if (ret <= 0)
    {
        return NULL;
    }
    //
    PACK_TYPE type;
    ret = recv(fd, &type, 4, 0);
    // printf("type=[%d], ret=[%d]\n", type, ret);
    if (ret <= 0)
    {
        return NULL;
    }
    //
    unsigned int fieldNum;
    ret = recv(fd, &fieldNum, 4, 0);
    // printf("fieldNum=[%d], ret=[%d]\n", fieldNum, ret);
    if (ret <= 0)
    {
        return NULL;
    }
    //
    msg_pack_t *pack = pack_create(type);
    for (int i = 0; i < fieldNum; i++)
    {
        int contentLen;
        ret = recv(fd, &contentLen, 4, 0);
        // printf("i=[%d], contentLen=[%d], ret=[%d]\n", i, contentLen, ret);
        if (ret <= 0)
        {
            pack_destroy(pack);
            return NULL;
        }
        //
        char *content = (char *)malloc(sizeof(char) * contentLen);
        ret = recv(fd, content, contentLen, 0);
        // printf("i=[%d], content=[%s], ret=[%d]\n", i, content, ret);
        // for(int i=0;i<contentLen;i++)
        //     printf("%02X ", content[i]);
        // printf("\n");
        if (ret <= 0)
        {
            free(content);
            pack_destroy(pack);
            return NULL;
        }
        //
        pack_add_field(pack, contentLen, content);
        // printf("i=[%d], pack.totalLen=[%d], pack.fieldNum=[%d]\n", i, pack->totalLen, pack->fieldNum);
        free(content);
    }
    // printf("解包完成，报文中的toatlLen=[%d]，计算的总长度=[%d]\n", totalLen, pack->totalLen);
    return pack;
}

field_t *pack_getField(msg_pack_t *pack, int index)
{
    if (index >= pack->fieldNum)
        return NULL;
    field_t *p = pack->startField;
    for (int i = 0; i < index; i++)
        p = p->next;
    return p;
}